package com.ktjy.controller;

import com.ktjy.service.UserDetailsServiceImpl;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
public class LoginController {
    @Autowired
    UserDetailsService userDetailsService;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Autowired
    RedisTemplate redisTemplate;

    @PostMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        HttpSession session){
        //1.根据用户名查询用户信息
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);

        //控制密码错误次数 一个账号 密码错误次数最多3次  用户被锁住2分钟
        ValueOperations<String, Integer> valueOperations = redisTemplate.opsForValue();
        //获取锁
        Integer lock = valueOperations.get("password::error::lock::" + username);
        //判断有没有上锁
        if(lock!=null&&lock==1){
            return "用户被锁住;请2分钟之后再来登录";
        }

        //2.匹配密码
        boolean matches = passwordEncoder.matches(password, userDetails.getPassword());

        Integer count = valueOperations.get("password::error::count::" + username);
        if(count==null){
            count=0;
        }
        //redis 存储2个键值对
        if(!matches){
            //1.计数器加1
            count++;
            valueOperations.set("password::error::count::" + username,count);

            //3.判断计数器是否大于等于3
            if(count>=3){
                //上锁
                valueOperations.set("password::error::lock::" + username,1,2, TimeUnit.HOURS);
                //2.计算器清空
                count=0;
                redisTemplate.delete("password::error::count::" + username);
                return "用户被锁住;请2分钟之后再来登录";
            }
            return "密码错误";
        }else{
            //2.计算器清空
            count=0;
            redisTemplate.delete("password::error::count::" + username);
        }

        //3.将用户信息存储起来 （jwt令牌,redis）
        //ThreadLocal
//        UsernamePasswordAuthenticationToken authenticationToken =
//                new UsernamePasswordAuthenticationToken(username,password,userDetails.getAuthorities());
//        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
//        session.setAttribute("SPRING_SECURITY_CONTEXT",SecurityContextHolder.getContext());

        //登录用户信息
        Map<String,Object> map=new HashMap<>();
        map.put("username",username);
        map.put("password",password);
        System.out.println(userDetails.getAuthorities());
        map.put("auth",userDetails.getAuthorities());

        long now=System.currentTimeMillis();
        long expiration=now+10*60*1000;

        //生成token(jwt令牌)
        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "zjgdzjgdzjgdzjgdzjgdzjgdzjgdzjgdzjgdzjgdzjgdzjgd") //指定加密算法和私钥
                .setClaims(map) //设置载荷
                .setExpiration(new Date(expiration))//设置token的过期时间
                .compact();

        return token;
    }

    @RequestMapping("/main")
//    @Secured("adminN")
    @PreAuthorize("hasAuthority('admin')")
    public String main(HttpSession session) {
        return "main";
    }
}
